#include <unordered_map>
#include "PrimitivesCounter.h"
#include "PrimitiveDirection.h"
#include "RunLengthStatistic.h"

#pragma once

// Does RLF for a given image.
class RLFEngine
{
public:
	// Initializes the object. Copies the pixel array.
	RLFEngine(int* inputPixels, int pixelsLength, int imageWidth, int sampleSizeX, int sampleSizeY);
	~RLFEngine(void);
	/* Calculates the chosen run length statistic for the image an returns it as an different image. */
	void calculateStatistics(PrimitiveDirection direction, int windowSizeX, int windowSizeY);
	
	int* getRLFImage(PrimitiveDirection direction, RunLengthStatistic statisctic);

	// Gets the pixel count of an output image.
	int getOutputPixelCount();
private:
	static const int outputImageCount = 15;

	/* An array containing pixels of the image.
	Each int contains one meaningful byte that represent
	the level of gray color intensity, as the images are in grayscale.
	Coordinates of pixels:
	X = i % imageWidth
	Y = i / imageWidth (on integers) */
	int* pixels;
	int pixelsLength;
	int imageWidth;
	int imageHeight;

	/* 15 images; first 5 is for horizontal, next 5 for vertical, last one for primitives in both directions.
	In one chain of 5 images the order is: SPE, LPE, GLU, PLU, PP.*/
	int** outputPixels;
	int outputPixelsLength;
	int outputImageWidth;
	int outputImageHeight;
	
	int sampleSizeX;
	int sampleSizeY;

	PrimitivesCounter *counter;

	/*Calculates properties of an output image and creates an array fo them.
	The bigger the sample the smaller they will be compared to the original image.
	This is because one sample from input translates to one pixel in the output image.*/
	void createOutputArrays();

	/* Calculates short primitive emphasis for a part of the image an returns it as an different image. */
	int calculateWindowSPE(unordered_map <int, unordered_map <int, int>*>* primitives, int primitivesCount, int xStart, int xEnd, int yStart, int yEnd, PrimitiveDirection direction);
	/* Calculates int primitive emphasis for a part of the image an returns it as an different image. */
	int calculateWindowLPE(unordered_map <int, unordered_map <int, int>*>* primitives, int primitivesCount, int xStart, int xEnd, int yStart, int yEnd, PrimitiveDirection direction);
	/* Calculates gray-level uniformity for a part of the image an returns it as an different image. */
	int calculateWindowGLU(unordered_map <int, unordered_map <int, int>*>* primitives, int primitivesCount, int xStart, int xEnd, int yStart, int yEnd);
	/* Calculates primitive length uniformity for a part of the image an returns it as an different image.
	This method needs primitives ordered in another way.*/
	int calculateWindowPLU(unordered_map <int, unordered_map <int, int>*>* primitives, int primitivesCount, int xStart, int xEnd, int yStart, int yEnd);
	/* Calculates primitive percentage for a part of the image an returns it as an different image. */
	int calculateWindowPP(unordered_map <int, unordered_map <int, int>*>* primitives, int primitivesCount, int xStart, int xEnd, int yStart, int yEnd, PrimitiveDirection direction);

	// Gets the proper position of the image in outputPixels array.
	int getImageIndex(PrimitiveDirection direction, RunLengthStatistic statisctic);

	// Scales value from its given range to <0, 255>
	double scaleToColor(double value, double min, double max);

	double getMaxPrimitiveLength(PrimitiveDirection direction, int xStart, int xEnd, int yStart, int yEnd);
};

